package eu.webhib.webblog.gui.application;

import java.util.*;
import javax.servlet.http.*;
import org.apache.log4j.Logger;

import eu.webhib.frmwrk.jsf.utils.JsfUtil;

import eu.webhib.webblog.application.*;
import eu.webhib.webblog.gui.controller.*;

//
public class GuiApplication extends eu.webhib.frmwrk.servlet.AbstractApplication {

   private static final Logger log = Logger.getLogger(GuiApplication.class);
   //
   public static final String sessionDataObjectName = "sess";
   public static final String authenticationObjectName = "auth";
   //
   private static String baseUrl = null;
   private static String contextPath = null;
   //
   private static final String errorPage = "error/error";
   //
   private static final String userAdminFolder = "user/";
   private static final String loginPage = userAdminFolder + "login";
   private static final String notAtLoggedInState = userAdminFolder + "notatloggedin";
   //
   public static final String registerConfirmPage = userAdminFolder + "regconfirm";
   public static final String passwordResetConfirmPage = userAdminFolder + "pwresetconfirm";
   public static final String emailConfirmPage = userAdminFolder + "emailconfirm";

   // called at application startup from WebContextListener
   public static void startup() {
      log.info("startup");
      // singleton
      setInstance(new GuiApplication());

      Application.startup();
   }

   // callback from framework
   @Override
   public void setRequestFinished(HttpServletRequest request, String pagePath) {
      if (request.getMethod().equals("GET")) {
         if (!isUserAdminPage(pagePath)) {
            // remember if it was a GET request and not an user administration page
            getSessionData(request.getSession()).setHistoryPage(pagePath);
         }
      }
   }

   @Override
   public String getErrorPageURI() {
      return contextPath + errorPage;
   }

   // Session Handling  ------------------------------------------------------------
   //
   public static SessionData getSessionData() {
      return getSessionData(JsfUtil.getSession());
   }

   private static SessionData getSessionData(HttpSession session) {
      assert session != null;
      SessionData sess = (SessionData) session.getAttribute(sessionDataObjectName);
      if (sess == null) {
         session.setAttribute(sessionDataObjectName, sess = new SessionData());
      }
      return sess;
   }

   public static Authentication getAuthenticationData() {
      HttpSession session = JsfUtil.getSession();
      assert session != null;
      Authentication auth = (Authentication) session.getAttribute(authenticationObjectName);
      if (auth == null) {
         session.setAttribute(authenticationObjectName, auth = new Authentication());
      }
      return auth;
   }

   public static boolean isAuthenticated() {
      return getAuthenticationData().isAuthenticated();
   }

   public static void moveToNewSession() {
      // get current (old) session
      HttpSession oldSession = JsfUtil.getSession();

      // retrieve the attributes we have to move (having th SessionMoveIntf marker interface)
      Map<String, Object> attrsToMove = new HashMap<String, Object>();
      Enumeration<String> attrs = oldSession.getAttributeNames();
      while (attrs.hasMoreElements()) {
         String attrName = attrs.nextElement();
         Object attr = oldSession.getAttribute(attrName);
         if (attr instanceof SessionMoveIntf) {
            attrsToMove.put(attrName, attr);
         }
      }
      // ivalidate current session
      oldSession.invalidate();

      // create new session
      HttpSession newSession = JsfUtil.getSession();
      log.debug("oldSessionId: " + oldSession.getId() + " newSessionId: " + newSession.getId());
      assert !oldSession.getId().equals(newSession.getId());

      // set the attribute objects in the new session
      for (Map.Entry<String, Object> attr : attrsToMove.entrySet()) {
         newSession.setAttribute(attr.getKey(), attr.getValue());
         log.trace("moved attribute: " + attr.getKey());
      }
      log.info("session moved to: " + newSession.getId());
   }

   // URL Handling  ------------------------------------------------------------
   //
   // called at session initialization by SessionData contructor
   public static void initContextURLs(HttpServletRequest req) {
      if (contextPath == null) {
         contextPath = req.getContextPath() + '/';
         log.info("contextPath: " + contextPath);
         baseUrl = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + contextPath;
         log.info("baseUrl: " + baseUrl);
         // propagate to mailing system
         ApplMail.setup(baseUrl);
      }
   }

   public static String getBaseUrl() {
      return baseUrl;
   }

   public static String getContextPath() {
      return contextPath;
   }

   public static String getLoginPageURI() {
      return contextPath + loginPage;
   }

   public static String getNotAtLoggedInStatePageURI() {
      return contextPath + notAtLoggedInState;
   }

   public static String getURIofPage(String page) {
      return contextPath + page;
   }

   private static boolean isUserAdminPage(String pagePath) {
      log.debug("isUserAdminPage: " + pagePath);
      return pagePath.startsWith(userAdminFolder);
   }

   public static String getHistroyPageURI() {
      return contextPath + getSessionData().getHistoryPage();
   }
}
